package com.lwm.demo.factory;

import com.lwm.demo.service.IAccountService;
import com.lwm.demo.utils.TransactionManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Repository;

import javax.annotation.Resource;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * 创建Service的代理对象
 *
 * @author liweimin
 * @date 2021/6/10 23:27
 * @since
 */
@Component
public class BeanFactory {

    private IAccountService accountService;

    private TransactionManager transactionManager;

    @Autowired
    public void setTransactionManager(TransactionManager transactionManager) {
        this.transactionManager = transactionManager;
    }

    @Autowired
    public void setAccountService(IAccountService accountService) {
        this.accountService = accountService;
    }

    @Bean(name = "transactionService")
    public IAccountService getAccountService() {
        IAccountService service = (IAccountService) Proxy.newProxyInstance(IAccountService.class.getClassLoader(), new Class[]{IAccountService.class}, new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                Object returnValue = null;

                try {
                    //1、开启事务
                    transactionManager.start();
                    //2.执行操作
                    returnValue = method.invoke(accountService, args);
                    //3.提交事务
                    transactionManager.commit();

                    return returnValue;
                } catch (Exception e) {
                    //4.回滚操作
                    transactionManager.rollback();
                    e.printStackTrace();
                    throw new RuntimeException();
                } finally {
                    //6.释放连接
                    transactionManager.release();
                }
            }
        });
        return service;
    }
}
